from typing import Dict, List, Any, Optional
from datetime import datetime
from pkg.tools import utils
from .model.response import NoteDetail, CommentInfo, NotesResult, NoteDetail, Hots, SearchNote

class XHSDataTransformer:
    """小红书数据转换器"""
    
    @staticmethod
    def transform_search_note(item: Dict) -> Optional[SearchNote]:
        """转换搜索笔记信息"""
        try:
            if not item or item.get("model_type") in ("rec_query", "hot_query"):
                return None
             # 从note_card中获取数据
            note_card = item.get("note_card", {})
            
            # 获取封面图
            cover = note_card.get("cover", {})
            cover_image = cover.get("url_default") or cover.get("url_pre", "")
            
            # 构建笔记链接
            note_id = item.get("id", "")
            xsec_token = item.get("xsec_token", "")
            link = f"https://www.xiaohongshu.com/explore/{note_id}?xsec_token={xsec_token}" if note_id and xsec_token else ''
            
            title = note_card.get("display_title", "")

            # 处理类型，只处理 video 和 normal 类型
            type = note_card.get("type", "")
            if type == "video":
                type = "视频"
            elif type == "normal":
                type = "笔记"
            else:
                type = "未知"
            
            # 提取图片列表
            images_urls = []
            for image in note_card.get("image_list", []):
                url = next(
                    (info["url"] for info in image.get("info_list", []) if info.get("image_scene") == "WB_DFT"),
                    next((info["url"] for info in image.get("info_list", []) if info.get("image_scene") == "WB_PRV"), '')
                )
                if url:
                    images_urls.append(url)
            # 处理用户信息
            user_data = note_card.get("user", {})
            user_id = user_data.get("user_id", None)
            user_link = f"https://www.xiaohongshu.com/user/profile/{user_id}?xsec_token={user_data.get('xsec_token')}" if user_id and user_data.get("xsec_token") else None
            nickname = user_data.get("nickname", None)
            avatar = user_data.get("avatar", None)
        
            # 处理互动信息
            interact_info = note_card.get("interact_info", {})
            likes = utils.parse_fuzzy_number_with_random(interact_info.get("liked_count", 0))

            note_data = {
                "id": note_id,
                "link": link,
                "type": type,
                "title": title,
                "cover_image": cover_image,
                "images": images_urls,
                "likes": likes,
                "user": {
                    "id": user_id,
                    "nickname": nickname,
                    "link": user_link,
                    "avatar": avatar,
                },  
            }
            
            return SearchNote(**note_data)
        except Exception as e:
            utils.logger.error(f"[小红书数据转换] 转换笔记信息失败: {e}")
            # TODO: 后续完善异常处理
            return None

    @classmethod
    def transform_note_detail(cls, 
                            note: Dict, 
                            from_html: bool = True) -> Optional[NoteDetail]:
        """转换笔记详情
        
        Args:
            note: 笔记详情数据
            comments: 评论数据
            search_note: 搜索结果中的笔记数据，用于复用基础信息
            from_html: 是否来自HTML接口的数据
        """
        try:
            # 1. 转换笔记详情
            note_info = cls._transform_detail_note(note, from_html)

            # 2. 创建详情对象
            note_detail = NoteDetail(note=note_info)
            

            return note_detail
        except Exception as e:
            utils.logger.error(f"[小红书数据转换] 转换笔记详情失败: {e}")
            return None



    @staticmethod
    def transform_comment(comment: Dict) -> Optional[CommentInfo]:
        """转换评论信息"""
        try:
            if not comment:
                return None
                
            return CommentInfo(
                comment_id=comment.get("comment_id", ""),
                content=comment.get("content", ""),
                user_id=comment.get("user_id", ""),
                nickname=comment.get("nickname", ""),
                time=comment.get("time", ""),
                like_count=comment.get("like_count", 0),
                sub_comment_count=comment.get("sub_comment_count", 0)
            )
        except Exception as e:
            utils.logger.error(f"[小红书数据转换] 转换评论信息失败: {e}")
            return None

    @classmethod
    def transform_notes_result(cls, data: Dict, include_media: bool = False) -> NotesResult:
        """转换笔记列表结果"""
        try:
            if not data:
                return NotesResult(notes=[], total=0, has_more=False)

            notes = []
            items = data.get("items", [])
            
            for item in items:
                note = cls.transform_search_note(item, include_media)
                if note:
                    notes.append(note)

            return NotesResult(
                notes=notes,
                total=len(notes),
                cursor=data.get("cursor"),
                has_more=data.get("has_more", False)
            )
        except Exception as e:
            utils.logger.error(f"[小红书数据转换] 转换笔记列表结果失败: {e}")
            return NotesResult(notes=[], total=0, has_more=False)


    @classmethod
    def _transform_detail_note(cls, note: Dict, from_html: bool = True) -> Optional[NoteDetail]:
        """转换详情数据"""
        try:
            if not note:
                return None

            # 1. 提取基础信息
            if from_html:
                note_id = note.get("note_id")
                note_data = {
                    "id": note_id,
                    "link": f"https://www.xiaohongshu.com/explore/{note_id}" if note_id else None,
                    "type": "视频" if note.get("type") == "video" else "笔记",
                    "title": note.get("title", ""),
                    "content": note.get("desc", ""),
                    "ip_location": note.get("ip_location", "未知IP所在地"),
                    "illegal_info": note.get("illegal_info", {}).get("desc", ""),
                }
            else:
                note_id = note.get("id")
                note_data = {
                    "id": note_id,
                    "link": f"https://www.xiaohongshu.com/explore/{note_id}" if note_id else None,
                    "type": note.get("type", "未知"),
                    "title": note.get("title", ""),
                    "content": note.get("content", ""),
                    "ip_location": note.get("ip_location", "未知IP所在地"),
                    "illegal_info": note.get("illegal_info", {}).get("desc", ""),
                }

            # 2. 添加各类信息
            note_data.update(cls._extract_media_info(note, from_html))  # 媒体信息
            note_data.update(cls._extract_stats_info(note, from_html))  # 统计信息
            note_data.update(cls._extract_tags_info(note, from_html))   # 标签信息
            note_data.update(cls._extract_time_info(note, from_html))   # 时间信息
            note_data.update(cls._extract_at_user_info(note,from_html))
            
            # 3. 添加用户信息
            user_info = cls._extract_basic_user_info(note, from_html)
            if user_info:
                note_data["user"] = user_info

            # 4. 添加安全令牌
            note_data["xsec_token"] = note.get("xsec_token", "")

            return NoteDetail(**note_data)
        except Exception as e:
            utils.logger.error(f"[小红书数据转换] 转换详情数据失败: {e}")
            return None

    @staticmethod
    def transform_hots(hot: Dict) -> Optional[Hots]:
        """转换热门榜单"""
        try:
            hot_data = {
                "title": hot.get("title", ""),
                "score": str(hot.get("score", 0) or  "0"),
                "word_type": hot.get("word_type", ""),
                "rank_change": str(hot.get("rank_change", 0) or "0")
            }
            return Hots(**hot_data)
        except Exception as e:
            utils.logger.error(f"[小红书数据转换] 转换热门榜单失败: {e}")
            return None

    @staticmethod
    def _extract_media_info(note: Dict, from_html: bool = True) -> Dict:
        """提取媒体信息"""
        try:
            if from_html:
                image_list = note.get("image_list", [])
                images_urls = []
                if image_list:
                    for image in image_list:
                        image_url = next(
                            (info["url"] for info in image.get("info_list", []) if info.get("image_scene") == "WB_DFT"),
                            next((info["url"] for info in image.get("info_list", []) if info.get("image_scene") == "WB_PRV"), '')
                        )
                        if image_url:
                            images_urls.append(image_url)
                       # 处理视频链接
                # 处理视频链接
                if note.get("type") == "video":
                    video_info = note.get("video", {})
                    video_link = None
                    # 尝试从 media 中获取视频链接
                    if "media" in video_info:
                        media = video_info["media"]
                        # 检查是否存在视频流数据
                        if "stream" in media:
                            stream_data = media["stream"]
                            # 按优先级尝试不同格式
                            for format in ["h264", "h265"]:
                                if format in stream_data:
                                    stream_list = stream_data[format]
                                    if stream_list and len(stream_list) > 0:
                                        stream = stream_list[0]
                                        # 优先使用 master_url
                                        if "master_url" in stream and stream["master_url"]:
                                            video_link = stream["master_url"]
                                            break
                                        # 其次使用 backup_url_1
                                        elif "backup_urls" in stream and stream["backup_urls"]:
                                            video_link = stream["backup_urls"]
                                            break
                    
                    else:
                        video_link = None
                else:
                    video_link = None  

                return {
                    "images": images_urls,
                    "video_link": video_link,
                    "cover_image": images_urls[0] if images_urls else None
                }
            else:
                images_urls = []
                for image in note.get("image_list", []):
                    image_url = next(
                        (info["url"] for info in image.get("info_list", []) if info.get("image_scene") == "WB_DFT"),
                        next((info["url"] for info in image.get("info_list", []) if info.get("image_scene") == "WB_PRV"), '')
                    )
                    if image_url:
                        images_urls.append(image_url)
                # 处理视频链接
                if note.get("type") == "video":
                    video_info = note.get("video", {})
                    video_link = None
                    
                    # 尝试从 media 中获取视频链接   
                    if "media" in video_info:   
                        media = video_info["media"]
                        if "stream" in media:
                            stream_data = media["stream"]
                            for format in ["h264", "h265"]:
                                if format in stream_data:
                                    stream_list = stream_data[format]   
                                    if stream_list and len(stream_list) > 0:
                                        stream = stream_list[0]
                                        if "master_url" in stream and stream["master_url"]:
                                            video_link = stream["master_url"]
                                            break   
                                        elif "backup_urls" in stream and stream["backup_urls"]:
                                            video_link = stream["backup_urls"]
                                            break
                    else:
                        video_link = None
                else:
                    video_link = None   
                return {
                    "images": images_urls,
                    "video_link": video_link,
                    "cover_image": images_urls[0] if images_urls else None
                }
        except Exception as e:
            utils.logger.error(f"[小红书数据转换] 提取媒体信息失败: {e}")
            return {}

    @staticmethod
    def _extract_stats_info(note: Dict, from_html: bool = True) -> Dict:
        """提取统计信息"""
        try:
            if from_html:
                interact_info = note.get("interact_info", {})
                return {
                    "likes": str(interact_info.get("liked_count", "0")),
                    "comments": str(interact_info.get("comment_count", "0")),
                    "collects": str(interact_info.get("collected_count", "0")),
                    "shares": str(interact_info.get("share_count", "0"))
                }
            else:
                interact_info = note.get("interact_info", {})
                return {
                    "likes": str(note.get("likes", "0")),
                    "comments": str(interact_info.get("comment_count", "0")),
                    "collects": str(interact_info.get("collected_count", "0")),
                    "shares": str(interact_info.get("share_count", "0"))
                }
        except Exception as e:
            utils.logger.error(f"[小红书数据转换] 提取统计信息失败: {e}")
            return {} 
        
    @staticmethod
    def _extract_tags_info(note: Dict, from_html: bool = True) -> Dict:
        """提取标签信息"""
        try:
            if from_html:
                tags = []
                for tag in note.get("tags", []):
                    tag_name = tag.get("name", "")
                    if tag_name:
                        tags.append(tag_name)
            else:
                tags = note.get("tags", [])
            
            return {"tags": tags}
        except Exception as e:
            utils.logger.error(f"[小红书数据转换] 提取标签信息失败: {e}")
            return {"tags": []}
        

    @staticmethod
    def _extract_time_info(note: Dict, from_html: bool = True) -> Dict:
        """提取时间信息"""
        try:
            if from_html:
                # 处理时间
                time = note.get("time", datetime.now().timestamp())/1000
                last_update_time = note.get("last_update_time", datetime.now().timestamp())/1000
                # 转换为 datetime 对象并格式化
                time = datetime.fromtimestamp(time).strftime("%Y-%m-%d %H:%M:%S")
                last_update_time = datetime.fromtimestamp(last_update_time).strftime("%Y-%m-%d %H:%M:%S")
                return {
                    "time": time,
                    "last_update_time": last_update_time
                }
            else:
                # 处理时间
                time = note.get("time", datetime.now().timestamp())/1000
                last_update_time = note.get("last_update_time", datetime.now().timestamp())/1000
                # 转换为 datetime 对象并格式化
                time = datetime.fromtimestamp(time).strftime("%Y-%m-%d %H:%M:%S")
                last_update_time = datetime.fromtimestamp(last_update_time).strftime("%Y-%m-%d %H:%M:%S")
                return {
                    "time": time,
                    "last_update_time": last_update_time
                }
        except Exception as e:
            utils.logger.error(f"[小红书数据转换] 提取时间信息失败: {e}")
            return {} 
        
    @staticmethod
    def _extract_basic_user_info(note: Dict, from_html: bool = True) -> Dict:
        """提取基础用户信息"""
        
        try:
            note_user = note.get("user", {})
            return {
                "id": note_user.get("user_id"),
                "nickname": note_user.get("nickname") or note_user.get("nick_name"),
                "avatar": note_user.get("avatar"),
                "link": f"https://www.xiaohongshu.com/user/profile/{note_user.get('user_id')}?xsec_token={note_user.get('xsec_token')}" if note_user.get("user_id") and note_user.get("xsec_token") else None
            }
        except Exception as e:
            utils.logger.error(f"[小红书数据转换] 提取时间信息失败: {e}")
            return {} 
        
    @staticmethod
    def _extract_at_user_info(note: Dict, from_html: bool = True) -> Dict:
        """提取@用户信息"""
        
        try:
            note_user = note.get("at_user_list", [])

            at_user_list = []
            for at_user in note_user:
                at_user_list.append({
                    "id": at_user.get("user_id"),
                    "nickname": at_user.get("nickname") or at_user.get("nick_name"),
                    "link": f"https://www.xiaohongshu.com/user/profile/{at_user.get('user_id')}?xsec_token={at_user.get('xsec_token')}" if at_user.get("user_id") and at_user.get("xsec_token") else None
                })
            return {"at_user_list": at_user_list}
        except Exception as e:
            utils.logger.error(f"[小红书数据转换] 提取时间信息失败: {e}")
            return {} 

